package org.erepublik.company.scanner;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import org.erepublik.company.Company;
import org.erepublik.company.ECountry;
import org.erepublik.company.EProductType;
import org.erepublik.company.Taxes;
import org.erepublik.company.generated.OfferT;
import org.erepublik.company.generated.OffersT;
import org.erepublik.company.product.EProductAttribute;
import org.erepublik.company.product.Product;
import org.erepublik.company.product.ProductDesign;
import org.erepublik.company.service.DatabaseProvider;
import org.erepublik.company.service.ICompanyCountryService;
import org.erepublik.company.service.IVatService;
import org.erepublik.company.service.JSONExchangeRateService;
import org.erepublik.company.utils.WebpageReader;
import org.erepublik.company.xml.XMLParsersers;

public abstract class ProductScanner<T extends Product> {

    protected EProductType productType = null;
    
    protected abstract T getNewProduct();
    protected abstract T[] getEmptyTable();
    protected abstract T[] getProductsFromCountry(ECountry eCountry, IVatService vatService, ICompanyCountryService companyService,
            JSONExchangeRateService currency) throws Exception;
    
    
    private static final long COMPANY_TIMEOUT = 1000*60*60*24*2; // 2 dni
    private DatabaseProvider databaseProvider = new DatabaseProvider();
    
    
    
    public T[] getProductsFromAllCountries(IVatService vatService, ICompanyCountryService companyService,
            JSONExchangeRateService currency) throws Exception  {
        
        ArrayList<T> alTickets = new ArrayList<T>();
        ECountry[] countries = ECountry.values();
        for (ECountry eCountry : countries) {
            T[] tickets = getProductsFromCountry(eCountry, vatService, companyService, currency);
            for (T ticket : tickets) {
                alTickets.add(ticket);
            }
        }
        
        T[] allTicketsTable = alTickets.toArray(getEmptyTable());
    
        return allTicketsTable;
    }


    
    
    
    
    
    
    // cena w api jest BEZ vatu i import taxa, wiec trzeba te rzeczy doliczyc
    protected T[] getProductList(ECountry country, ProductDesign design, IVatService vatService, ICompanyCountryService companyService,
            JSONExchangeRateService currency) throws Exception {
        String obiekt = null;
        if (productType!=null)
            obiekt = productType.toString();
        else 
            obiekt = getNewProduct().getClass().getSimpleName();
            
        System.out.println("Parsuje "+obiekt+" z " + country + " o parametrach: " + design);
        InputStream stream = WebpageReader.getStreamToIrl("http://api.erepublik.com/v2/feeds/market/" 
                + getNewProduct().getProductType().getErepublikId()
                + "/" + country.getErepublikId() + getAttributesAsUrl(design ));
        OffersT products = XMLParsersers.parseProducts(stream);
        ArrayList<T> list = new ArrayList<T>();
        for (OfferT offer : products.getOffer()) {
            T product = XmlToProduct(offer, country, vatService, companyService, currency);
            list.add(product);
        }

        return list.toArray(getEmptyTable());
    }
    
    
    
    
    
    private String getAttributesAsUrl(ProductDesign design) {
        EProductAttribute[] attributes = EProductAttribute.getAllAttributes( design.getType() );
        String str = "";
        for (EProductAttribute eProductAttribute : attributes) {
            str += "/"+design.getAttributeValue(eProductAttribute);
        }
        return str;
    }
    
    
    
    
    protected T XmlToProduct(OfferT offer,
            ECountry country, IVatService vatService,
            ICompanyCountryService companyService, JSONExchangeRateService currency) throws Exception {
        HashMap<ECountry, Taxes> taxes = vatService.getVat();
        HashMap<ECountry, Double> exchangeRates = currency.getExchangeRates();
        T product = getNewProduct();
        product.setProductDesign(offer);
        
        
        long now = new Date().getTime();
        Company company = databaseProvider.getCompanyById(offer.getCompany().getId());
        if (company==null) {
        	company = new Company();
            company = companyService.getLocationOfCompanyById(offer.getCompany().getId());
            databaseProvider.save(company);
        } 
        else {
            if (now - company.getUpdateTime() > COMPANY_TIMEOUT) {
                company = companyService.getLocationOfCompanyById(offer.getCompany().getId());
                databaseProvider.updateObject(company);
            }
        }
        double price = offer.getPrice() + taxes.get(country).getVat(product.getProductType()) * offer.getPrice();
        if (company.getCountry() != country) {
            price += taxes.get(country).getImportTax(product.getProductType()) * offer.getPrice();
        }
        price = Math.round((price * 100.0)) / 100.0d;
        product.setPrice(price);
        product.setPriceInGold(price * exchangeRates.get(country));
        product.setQuantity(offer.getAmount());
        product.setCompanyOwner( company );
        product.setMarket(country);
        return product;
    }

    
}
